#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>

int main(){

    int n = 100; //numero maximo de threads

    omp_set_num_threads(n); //define o numero maximo de threads

    FILE *f;
    int tam=0, inicio, fim, cont=0, inicio_trecho[n+1], i, cont_trecho, n_caracteres_txt; //numero de caracteres do txt
    char *texto, c, palavra[100];

    f = fopen("shakespe.txt", "r");

    fseek(f, 0, SEEK_END); //posiciona o cursor no fim do arquivo

    n_caracteres_txt = ftell(f); //a ultima posicao do arquivo é igual ao numero de caracteres no txt

    //#pragma omp parallel for private(i) firstprivate(n_caracteres_txt, n)
    for(i=0;i<n;i++)
        inicio_trecho[i] = (int) (i*n_caracteres_txt / n); //dividindo o txt em n partes


    //#pragma omp parallel for private(i, c) firstprivate(n, f, inicio_trecho) ordered
    for(i=1;i<n;i++){ //para a segunda thread até a ultima
        fseek(f, inicio_trecho[i], SEEK_SET);  //posiciona o cursor no começo do trecho da thread
        c = fgetc(f);  //retorna o primeiro caracter do trecho da thread
        while((c >= 48 && c <= 57) || (c >= 65 && c<= 90) || (c >= 97 && c<= 122)) //se for letra ou numero, ou seja, esta no meio da palavra
            c = fgetc(f);  //avança para o proximo, até que nao seja mais uma letra ou numero
        inicio_trecho[i] = (ftell(f)) - 1; //o inicio do trecho da thread é definido
    }

    texto = (char *) malloc(n_caracteres_txt*sizeof(char)); //alocando memoria para o numero total de caracteres do txt

    if(texto == NULL) {
            printf("Malloc devolveu NULL!\n");
            exit(1);
    }

    fseek(f, 0, SEEK_SET); //posiciona o cursor no inicio do txt
    for(i=0;i<n_caracteres_txt;i++) //para o primeiro caracter do txt, até o ultimo
        texto[i] = fgetc(f); //copia o caracter para a memoria

    fclose(f);
    inicio_trecho[n] = n_caracteres_txt;

    #pragma omp parallel firstprivate(tam, inicio_trecho, texto) private(inicio, fim, c, palavra, cont_trecho) shared(cont)
    //bloco paralelo. As variaveis firstprivate ja foram inicializadas, as privates tem lixo e shared tambem ja foram inicializadas
    {
        cont_trecho = inicio_trecho[omp_get_thread_num()]; //cont_trecho recebe o inicio de cada thread
        //printf("Thread %d começou!!!!!!!!!!!!\n", omp_get_thread_num());

        while(1){
            if(cont_trecho == inicio_trecho[omp_get_thread_num()+1]-1)
                break;
            //printf("Sou a thread %d na posicao %d e com o caracter %c \n", omp_get_thread_num(), cont_trecho, c);

            c = texto[cont_trecho]; // c recebe o caracter atual

            if((c >= 48 && c <= 57) || (c >= 65 && c<= 90) || (c >= 97 && c<= 122)){ //se for letra(maiuscula ou minuscula) ou numero
                palavra[tam] = c; //adiciona o caracter ao vetor palavra
                tam++; //tamanho do vetor é incrementado
            }

            else if(c != 39) { // se c == ', ele nao faz nada. Vai pra proxima iteraao do while
                if(palavra[0] != 0){ //se já tem algum caracter no vetor palavra, vai ser analisada a ocorrencia de palindromo
                    inicio = 0;   //inicio da palavra
                    fim = tam-1;  //fim da palavra

                    if(tam % 2 == 1) //se a palavra tem numero impar de letras
                        tam = tam-1; //a iteração do for a seguir decrementada

                    for(inicio; inicio<(tam/2);){
                        if(palavra[inicio] != palavra[fim]){ //se a primeira e ultima letra forem diferentes, nao é palindromo. O mesmo é verificado para as proximas letras
                            break;
                        }
                        else{
                            if(inicio == (tam/2)-1){ //se chegar ao meio da palavra, quer dizer que é um palindromo
                                //printf("\nPALINDROMO!!!!   >>>>   %s", palavra);
                                cont++; //contador de palindromos
                            }
                        }

                        inicio++; //incrementa a primeira letra
                        fim--;    //decrementa a ultima letra
                    }

                    for(inicio=0;inicio<=tam;inicio++) //zerando o vetor palavra
                        palavra[inicio] = 0;
                    tam = 0; //tamanho do vetor = 0
                }
            }
            cont_trecho++; //incremento para pegar o proximo caracter do trecho
        }
        //printf("Thread %d terminou!!!\n", omp_get_thread_num());
    }
    free(texto);
    printf("\nNumero de Palindromos encontrados: %d\n", cont);
    return 0;
}
